"use client";

import { useState, useCallback, createContext, useContext, useEffect, type ReactNode } from "react";
import {
  useExternalStoreRuntime,
  type ThreadMessageLike,
  type AppendMessage,
  AssistantRuntimeProvider,
} from "@assistant-ui/react";
import { SidecarClient } from "@/api/sidecar";
import { useAssistantStore } from "@/store/assistant";
import { useSessionStore } from "@/store/session";

// Sub-agent execution status
export interface SubAgentExecution {
  id: string;
  agentId: string;
  agentName: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  startTime: Date;
  endTime?: Date;
  input?: string;
  output?: string;
  error?: string;
}

// Tool call execution status
export interface ToolCallExecution {
  id: string;
  name: string;
  status: 'pending' | 'running' | 'success' | 'error';
  startTime: Date;
  endTime?: Date;
  parameters?: any;
  result?: any;
  error?: string;
}

// Sub-agent context
interface SubAgentContextType {
  executions: SubAgentExecution[];
  activeExecutions: SubAgentExecution[];
  addExecution: (execution: SubAgentExecution) => void;
  updateExecution: (id: string, updates: Partial<SubAgentExecution>) => void;
  clearExecutions: () => void;
  toolCalls: ToolCallExecution[];
  activeToolCalls: ToolCallExecution[];
  addToolCall: (toolCall: ToolCallExecution) => void;
  updateToolCall: (id: string, updates: Partial<ToolCallExecution>) => void;
  clearToolCalls: () => void;
}

const SubAgentContext = createContext<SubAgentContextType | null>(null);

export const useSubAgentContext = () => {
  const context = useContext(SubAgentContext);
  if (!context) {
    throw new Error('useSubAgentContext must be used within SidecarRuntimeProvider');
  }
  return context;
};

// Convert our Sidecar message format to assistant-ui format
const convertMessage = (message: ThreadMessageLike): ThreadMessageLike => {
  return message;
};

export function SidecarRuntimeProvider({
  children,
  sidecarUrl = "http://localhost:3000",
}: {
  children: ReactNode;
  sidecarUrl?: string;
}) {
  const [messages, setMessages] = useState<ThreadMessageLike[]>([]);
  const [isRunning, setIsRunning] = useState(false);
  const [executions, setExecutions] = useState<SubAgentExecution[]>([]);
  const [toolCalls, setToolCalls] = useState<ToolCallExecution[]>([]);
  const client = new SidecarClient(sidecarUrl);

  // 获取当前选中的助手
  const selectedAssistant = useAssistantStore((state) => state.selectedAssistant);

  // 获取 session store
  const currentSession = useSessionStore((state) => state.currentSession);
  const createSession = useSessionStore((state) => state.createSession);
  const addMessage = useSessionStore((state) => state.addMessage);

  // 当开始新对话时，自动创建 session
  // 注意：只在组件首次挂载且没有 session 时创建，避免重复创建
  useEffect(() => {
    if (!currentSession) {
      createSession(
        selectedAssistant ? `与 ${selectedAssistant.name} 的对话` : '新对话',
        selectedAssistant?.id
      ).catch((error) => {
        console.error('Failed to create session:', error);
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // 只在组件挂载时执行一次

  // 当 session 切换时，加载历史消息
  useEffect(() => {
    if (currentSession && currentSession.messages) {
      // 将 session 的消息转换为 ThreadMessageLike 格式
      const sessionMessages: ThreadMessageLike[] = currentSession.messages.map((msg) => ({
        id: msg.id,
        role: msg.role as 'user' | 'assistant',
        content: [{ type: 'text' as const, text: msg.content }],
        createdAt: new Date(msg.timestamp),
      }));
      
      setMessages(sessionMessages);
    } else {
      // 如果没有 session 或 session 没有消息，清空消息列表
      setMessages([]);
    }
  }, [currentSession]);

  // Sub-agent execution management
  const addExecution = useCallback((execution: SubAgentExecution) => {
    setExecutions((prev) => [...prev, execution]);
  }, []);

  const updateExecution = useCallback((id: string, updates: Partial<SubAgentExecution>) => {
    setExecutions((prev) =>
      prev.map((exec) => (exec.id === id ? { ...exec, ...updates } : exec))
    );
  }, []);

  const clearExecutions = useCallback(() => {
    setExecutions([]);
  }, []);

  const activeExecutions = executions.filter(
    (exec) => exec.status === 'pending' || exec.status === 'running'
  );

  // Tool call management
  const addToolCall = useCallback((toolCall: ToolCallExecution) => {
    setToolCalls((prev) => [...prev, toolCall]);
  }, []);

  const updateToolCall = useCallback((id: string, updates: Partial<ToolCallExecution>) => {
    setToolCalls((prev) =>
      prev.map((call) => (call.id === id ? { ...call, ...updates } : call))
    );
  }, []);

  const clearToolCalls = useCallback(() => {
    setToolCalls([]);
  }, []);

  const activeToolCalls = toolCalls.filter(
    (call) => call.status === 'pending' || call.status === 'running'
  );

  const onNew = useCallback(
    async (message: AppendMessage) => {
      // Validate message content
      if (message.content.length !== 1 || message.content[0]?.type !== "text") {
        throw new Error("Only text content is supported");
      }

      const userText = message.content[0].text;

      // Add user message
      const userMessage: ThreadMessageLike = {
        role: "user",
        content: [{ type: "text", text: userText }],
        id: `user-${Date.now()}`,
        createdAt: new Date(),
      };
      setMessages((prev) => [...prev, userMessage]);

      // 保存用户消息到 session
      if (currentSession) {
        try {
          await addMessage(
            currentSession.id,
            'user',
            userText,
            { source: 'web' },
            selectedAssistant?.id
          );
        } catch (error) {
          console.error('Failed to save user message to session:', error);
        }
      }

      // Start streaming
      setIsRunning(true);
      const assistantId = `assistant-${Date.now()}`;
      let assistantText = "";

      try {
        // Stream response from Sidecar
        // 传递选中的助手 ID 到后端，启用 sub-agent 功能
        for await (const response of client.queryStream({
          prompt: userText,
          options: {
            model: "claude-sonnet-4",
            maxTurns: 10,
            includePartialMessages: true,
            subAgentId: selectedAssistant?.id, // ✅ 传递选中的助手 ID
          },
        })) {
          // Handle sub-agent events (if SDK provides them in the future)
          // TODO: Update when SDK types include sub-agent events
          if (response.type === "stream_event" && response.event) {
            const event = response.event as any;

            // Detect sub-agent invocation (heuristic based on message content)
            if (event.delta?.text) {
              const text = event.delta.text;

              // Check for sub-agent invocation patterns
              // This is a heuristic until SDK provides explicit sub-agent events
              if (text.includes('[Sub-Agent:') || text.includes('Invoking sub-agent')) {
                const match = text.match(/\[Sub-Agent:\s*([^\]]+)\]/);
                if (match) {
                  const agentName = match[1];
                  const executionId = `exec-${Date.now()}-${Math.random()}`;

                  addExecution({
                    id: executionId,
                    agentId: agentName.toLowerCase().replace(/\s+/g, '-'),
                    agentName,
                    status: 'running',
                    startTime: new Date(),
                    input: userText,
                  });
                }
              }
            }
          }

          // Handle streaming events with delta text
          if (response.type === "stream_event" && response.event?.delta?.text) {
            assistantText += response.event.delta.text;

            // Update or create assistant message
            setMessages((prev) => {
              const existingIndex = prev.findIndex((m) => m.id === assistantId);
              if (existingIndex >= 0) {
                // Update existing message
                return prev.map((m, i) =>
                  i === existingIndex
                    ? {
                        ...m,
                        content: [{ type: "text", text: assistantText }],
                      }
                    : m
                );
              } else {
                // Create new assistant message
                return [
                  ...prev,
                  {
                    role: "assistant",
                    content: [{ type: "text", text: assistantText }],
                    id: assistantId,
                    createdAt: new Date(),
                  },
                ];
              }
            });
          }
          // Handle final result
          else if (response.type === "result" && response.result) {
            // Extract text content from result message
            const resultMessage = response.result as any;
            let extractedText = '';

            if (typeof resultMessage.content === 'string') {
              extractedText = resultMessage.content;
            } else if (Array.isArray(resultMessage.content)) {
              extractedText = resultMessage.content
                .filter((block: any) => block.type === 'text')
                .map((block: any) => block.text)
                .join('');
            }

            // Only update if we have new content
            if (extractedText && extractedText !== assistantText) {
              assistantText = extractedText;
            }

            // Mark all running executions as completed
            executions.forEach((exec) => {
              if (exec.status === 'running') {
                updateExecution(exec.id, {
                  status: 'completed',
                  endTime: new Date(),
                  output: assistantText,
                });
              }
            });

            // Only update message if we have content
            if (assistantText) {
              setMessages((prev) => {
                const existingIndex = prev.findIndex((m) => m.id === assistantId);
                if (existingIndex >= 0) {
                  return prev.map((m, i) =>
                    i === existingIndex
                      ? {
                          ...m,
                          content: [{ type: "text", text: assistantText }],
                        }
                      : m
                  );
                } else {
                  return [
                    ...prev,
                    {
                      role: "assistant",
                      content: [{ type: "text", text: assistantText }],
                      id: assistantId,
                      createdAt: new Date(),
                    },
                  ];
                }
              });

              // 保存助手回复到 session
              if (currentSession) {
                try {
                  await addMessage(
                    currentSession.id,
                    'assistant',
                    assistantText,
                    { source: 'agent' },
                    selectedAssistant?.id
                  );
                } catch (error) {
                  console.error('Failed to save assistant message to session:', error);
                }
              }
            }
          }
        }
      } catch (error) {
        console.error("Error querying agent:", error);
        // Add error message
        setMessages((prev) => [
          ...prev,
          {
            role: "assistant",
            content: [
              {
                type: "text",
                text: `Error: ${error instanceof Error ? error.message : "Unknown error"}`,
              },
            ],
            id: `error-${Date.now()}`,
            createdAt: new Date(),
          },
        ]);
      } finally {
        setIsRunning(false);
      }
    },
    [client, selectedAssistant, currentSession, addMessage, addExecution, updateExecution, executions] // ✅ 添加依赖项
  );

  const runtime = useExternalStoreRuntime({
    messages,
    isRunning,
    setMessages: setMessages as any, // Type workaround for readonly array
    onNew,
    convertMessage,
  });

  const subAgentContextValue: SubAgentContextType = {
    executions,
    activeExecutions,
    addExecution,
    updateExecution,
    clearExecutions,
    toolCalls,
    activeToolCalls,
    addToolCall,
    updateToolCall,
    clearToolCalls,
  };

  return (
    <SubAgentContext.Provider value={subAgentContextValue}>
      <AssistantRuntimeProvider runtime={runtime}>
        {children}
      </AssistantRuntimeProvider>
    </SubAgentContext.Provider>
  );
}

